home *** CD-ROM | disk | FTP | other *** search
/ PD Collection CD 1 / PD Collection CD 1.iso / textual / pdftops / xpdf / c++ / Parser < prev    next >
Text File  |  1996-05-23  |  3KB  |  160 lines

  1. //========================================================================
  2. //
  3. // Parser.cc
  4. //
  5. // Copyright 1996 Derek B. Noonburg
  6. //
  7. //========================================================================
  8.  
  9. #ifdef __GNUC__
  10. #pragma implementation
  11. #endif
  12.  
  13. #include <stddef.h>
  14. #include "Object.h"
  15. #include "Array.h"
  16. #include "Dict.h"
  17. #include "Parser.h"
  18. #include "Error.h"
  19.  
  20. Parser::Parser(Lexer *lexer1) {
  21.   lexer = lexer1;
  22.   inlineImg = 0;
  23.   lexer->getObj(&buf1);
  24.   lexer->getObj(&buf2);
  25. }
  26.  
  27. Parser::~Parser() {
  28.   buf1.free();
  29.   buf2.free();
  30.   delete lexer;
  31. }
  32.  
  33. Object *Parser::getObj(Object *obj) {
  34.   char *key;
  35.   Stream *str;
  36.   Object obj2;
  37.   int num;
  38.  
  39.   // refill buffer after inline image data
  40.   if (inlineImg == 2) {
  41.     buf1.free();
  42.     buf2.free();
  43.     lexer->getObj(&buf1);
  44.     lexer->getObj(&buf2);
  45.     inlineImg = 0;
  46.   }
  47.  
  48.   // array
  49.   if (buf1.isCmd("[")) {
  50.     shift();
  51.     obj->initArray();
  52.     while (!buf1.isCmd("]") && !buf1.isEOF())
  53.       obj->arrayAdd(getObj(&obj2));
  54.     if (buf1.isEOF())
  55.       error(getPos(), "End of file inside array");
  56.     shift();
  57.  
  58.   // dictionary or stream
  59.   } else if (buf1.isCmd("<<")) {
  60.     shift();
  61.     obj->initDict();
  62.     while (!buf1.isCmd(">>") && !buf1.isEOF()) {
  63.       if (!buf1.isName()) {
  64.     error(getPos(), "Dictionary key must be a name object");
  65.     shift();
  66.       } else {
  67.     key = copyString(buf1.getName());
  68.     shift();
  69.     if (buf1.isEOF() || buf1.isError())
  70.       break;
  71.     obj->dictAdd(key, getObj(&obj2));
  72.       }
  73.     }
  74.     if (buf1.isEOF())
  75.       error(getPos(), "End of file inside dictionary");
  76.     if (buf2.isCmd("stream")) {
  77.       if ((str = makeStream(obj))) {
  78.     obj->initStream(str);
  79.       } else {
  80.     obj->free();
  81.     obj->initError();
  82.       }
  83.     } else {
  84.       shift();
  85.     }
  86.  
  87.   // indirect reference or integer
  88.   } else if (buf1.isInt()) {
  89.     num = buf1.getInt();
  90.     shift();
  91.     if (buf1.isInt() && buf2.isCmd("R")) {
  92.       obj->initRef(num, buf1.getInt());
  93.       shift();
  94.       shift();
  95.     } else {
  96.       obj->initInt(num);
  97.     }
  98.  
  99.   // simple object
  100.   } else {
  101.     buf1.copy(obj);
  102.     shift();
  103.   }
  104.  
  105.   return obj;
  106. }
  107.  
  108. Stream *Parser::makeStream(Object *dict) {
  109.   Object obj;
  110.   Stream *str;
  111.   int pos, length;
  112.  
  113.   // get stream start position
  114.   lexer->skipToNextLine();
  115.   pos = lexer->getPos() - 1;
  116.  
  117.   // get length
  118.   dict->dictLookup("Length", &obj);
  119.   if (obj.isInt()) {
  120.     length = obj.getInt();
  121.     obj.free();
  122.   } else {
  123.     error(getPos(), "Bad 'Length' attribute in stream");
  124.     obj.free();
  125.     return NULL;
  126.   }
  127.  
  128.   // make base stream
  129.   str = new FileStream(lexer->getStream()->getFile(), pos, length, dict);
  130.  
  131.   // get filters
  132.   str = str->addFilters(dict);
  133.  
  134.   // skip over stream data
  135.   lexer->getStream()->setPos(pos + length);
  136.  
  137.   // refill token buffers and check for 'endstream'
  138.   shift();  // kill '>>'
  139.   shift();  // kill 'stream'
  140.   if (buf1.isCmd("endstream"))
  141.     shift();
  142.   else
  143.     error(getPos(), "Missing 'endstream'");
  144.  
  145.   return str;
  146. }
  147.  
  148. void Parser::shift() {
  149.   if (inlineImg > 0)
  150.     ++inlineImg;
  151.   else if (buf2.isCmd("ID"))
  152.     inlineImg = 1;
  153.   buf1.free();
  154.   buf1 = buf2;
  155.   if (inlineImg > 0)        // don't buffer inline image data
  156.     buf2.initNull();
  157.   else
  158.     lexer->getObj(&buf2);
  159. }
  160.